package cn.edu.sdjzu.xg.eagle.filter;

/**
 * @author tg.si@188.com
 * @todo
 * @since 2024/4/16 16:39
 */

import cn.edu.sdjzu.xg.eagle.util.ConfigUtil;
import cn.edu.sdjzu.xg.eagle.util.JwtUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//@WebFilter(filterName = "Auth", urlPatterns = {"/*"})
public class JwtAuthFilter implements Filter {
    //ThreadLocal 可以将数据与特定的线程关联起来,这意味着每个线程都可以有自己的数据副本，
    // 而不会影响其他线程。这有助于避免在多线程环境中共享数据的问题。
    // 当线程结束时，ThreadLocal 会自动释放与该线程关联的数据。这有助于避免内存泄漏问题。
    // 可以简化代码，因为你不需要显式地传递数据。你可以在一个地方设置数据，然后在其他地方访问它，而不需要将数据作为参数传递给方法。
    private static final ThreadLocal<String> currentUserId = new ThreadLocal<>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化过滤器
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 获取请求路径
        String path = request.getRequestURI();
        System.out.println("path=" + path);
        String loginUrl = ConfigUtil.getProperty("login.url");
        // 如果无须验证，直接放行
        if (path.endsWith(loginUrl) || path.endsWith("/bysj/")) {
            filterChain.doFilter(request, response);
            return;
        }

        // 从请求头中的Authorization字段获取Token
        String authorizationHeader = request.getHeader("Authorization");
        if(authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")){
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 验证失败，返回未授权状态码
        }else {
            String token = authorizationHeader.substring(7).trim(); // 移除前缀"Bearer"和空格
            // 验证Token
            if(JwtUtil.validateToken(token)){
                //解析token的subject
                DecodedJWT decodedJWT = JWT.decode(token);
                String subject = decodedJWT.getSubject();
                // 将 subject 存储在 ThreadLocal 变量中
                currentUserId.set(subject);
                filterChain.doFilter(request, response); // 验证通过，继续处理请求
                //当前请求结束，显式地清除 ThreadLocal 变量，免得内存压力增大
                currentUserId.remove();
            }else{
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 验证失败，返回未授权状态码
            }
        }
    }

    @Override
    public void destroy() {
        // 销毁过滤器
    }

    public static String getCurrentUserId() {
        return currentUserId.get();
    }
}